package com.scott.itcast.lock;

import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 读写锁要实现的目标。
 * 读中有读 ： 可以一起读  A在读 B也在读  这个可以。
 * 但是读中没有写，写中没有读。写中也没有写。
 * 读写锁既能提高性能，有能互斥。只有在java5中才有。java4中是没有的
 * 
 * 如果直接用Lock就不行。因为Lock不管是读还是写别人都进不来了。
 * 而读写锁的目标是要： 允许多个线程1起读。 只是读写分开。写和写也分开。
 * 
 */
public class ReadWriteLockTest {
	public static void main(String[] args) {
		final Queue3 q3 = new Queue3();
		
		for(int i=0;i<3;i++){
			//3个线程去读
			new Thread(){
				public void run(){
					while(true){
						q3.get();						
					}
				}
				
			}.start();

			//3个线程去写
			new Thread(){
				public void run(){
					while(true){
						//10000以内的随机数
						q3.set(new Random().nextInt(10000));
					}
				}			
				
			}.start();
		}//for
	}//main
}//ReadWriteLockTest

class Queue3{
	//共享数据，只能有一个线程能写该数据，但可以有多个线程同时读该数据。
	private Object shareData = null;
	
	//读写锁
	ReadWriteLock rwl = new ReentrantReadWriteLock();
	
	public void get(){
		//读锁
		rwl.readLock().lock();
		try {
			System.out.print(Thread.currentThread().getName() + "准备读数据...");
			Thread.sleep((long)(Math.random()*1000));
			
			//读 就是拿到数据
			System.out.println(Thread.currentThread().getName() + "已经读好数据：" + shareData);			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			rwl.readLock().unlock();
		}
	}//get 拿到数据
	
	public void set(Object data){

		//写锁
		rwl.writeLock().lock();
		try {
			System.out.print(Thread.currentThread().getName() + "准备写数据...");					
			Thread.sleep((long)(Math.random()*1000));
			
			//写 就是给数据赋值
			this.shareData = data;		
			System.out.println(Thread.currentThread().getName() + "已经写好数据：" + data);					
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			rwl.writeLock().unlock();
		}
		
	
	}//put 给数据赋值
}//Queue3